package com.yhy.common.core.result;


import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.yhy.common.core.exception.BizException;
import com.yomahub.tlog.context.TLogContext;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;

/**
 * 响应信息主体
 *
 * @param <T>
 * @author jax-li
 */
@ApiModel(value = "统一响应对象")
@Data
@NoArgsConstructor
@Accessors(chain = true)
@JsonInclude(Include.NON_NULL)
public class Result<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "状态", example = "true")
    private boolean success;

    @ApiModelProperty(value = "业务代码", example = "0")
    private Integer code;

    @ApiModelProperty(value = "内容", example = "ok")
    private String message;

    @ApiModelProperty(value = "响应体", dataType = "Object")
    private T data;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @ApiModelProperty(value = "系统时间")
    private Date serverTime;

    @ApiModelProperty(value = "请求路径", example = "0")
    private String path;

    @ApiModelProperty(value = "追踪id")
    private String traceId;

    @ApiModelProperty(value = "跨度id")
    private String spanId;

    public static <T> Result<T> ok() {
        return ok(null);
    }

    public static <T> Result<T> ok(T data) {
        return result(Boolean.TRUE, ResultCode.OK.getCode(), ResultCode.OK.getMsg(), data);
    }

    public static <T> Result<T> fail(BizException ex) {
        return fail(ex.getCode(), ex.getMessage());
    }

    public static <T> Result<T> fail(Exception ex) {
        return fail(ResultCode.FAIL.getCode(), ex.getLocalizedMessage());
    }

    public static <T> Result<T> fail(ResultEnum resultCode) {
        return fail(resultCode.getCode(), resultCode.getMsg());
    }

    public static <T> Result<T> fail(String message) {
        return fail(ResultCode.FAIL.getCode(), message);
    }

    private static <T> Result<T> fail(Integer code, String message) {
        return result(Boolean.FALSE, code, message, null);
    }

    private static <T> Result<T> result(boolean success, int code, String message, T data) {
        Result<T> result = new Result<>();
        result.setSuccess(success);
        result.setCode(code);
        result.setMessage(message);
        result.setData(data);
        result.setTraceId(TLogContext.getTraceId());
        result.setSpanId(TLogContext.getSpanId());
        result.setServerTime(new Date());
        return result;
    }

}
